#include "widget.h"
#include <QDebug>
#include <QHostAddress>
#include <QIcon>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QPixmap>
#include <QVector>
#include <QtCharts/QAreaSeries>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtDebug>
#include "QChartView"
#include "QDebug"
#include "QLineSeries"
#include "QList"
#include "QPointF"
#include "QScatterSeries"
#include "QTime"
#include "QTimer"
#include "QValueAxis"
#include "QtCharts/QChart"
#include "qmath.h"
#include "ui_widget.h"
QT_CHARTS_USE_NAMESPACE
QChart* m_chart;
QLineSeries* m_series;
int maxSize = 5000;
double sum_ber = 0;
double sum_bler = 0;
double sum_snr = 0;
double sum_noise = 0;
double sum_signal = 0;
double sum_meansnr = 0;
double temp_snr = 0;
// QTimer updateTimer;
int timeId;

Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget),
    client(new QTcpSocket(this)), myTimer(new QTimer(this)),
    checked(false), checked_circle(false), isPaused(false) {


    ui->setupUi(this);
    ui->ip->setText("127.0.0.1");
    ui->port->setText("8000");

    initChart(ui->huatu_3, berSeries, berChart, "BER Chart", "Number of Packet", "BER(%)", QColor(0, 255, 0));
    initChart(ui->huatu_2, blerSeries, blerChart, "BLER Chart", "Number of Packet", "BLER(%)", QColor(255, 255, 0));
    initChart(ui->huatu, snrSeries, snrChart, "SNR Chart", "Number of Packet", "SNR(%)", QColor(0, 255, 0));
    addSecondSeries(snrChart, tsnrSeries, Qt::red);


    myTimer = new QTimer(this);
    connect(myTimer,&QTimer::timeout,[=](){
        int ret = client->write("wake hands");
        if(ret==-1)
        {
            if(!ip.contains(ui->ip->text())){
                ip.append(ui->ip->text().append('\n'));
            }
            if(!port.contains(ui->port->text())){
                port.append(ui->port->text().append('\n'));
            }
            ui->ip->setToolTip(ip);
            ui->port->setToolTip(port);
            client->connectToHost(QHostAddress(ui->ip->text()),ui->port->text().toInt());
            QMessageBox::information(this,tr("提示"),tr("连接断开，正在重新连接！"),QMessageBox::Ok);
            client->write("CONTINUOUSREQ2\r\n\r\n");

        }
        else {
            qDebug()<<"已连接";
        }
    });

    connect(client, &QTcpSocket::readyRead, this, [=]() {
        if (client->state() == QAbstractSocket::UnconnectedState )  //已断开连接则进入if{}
        {
           QMessageBox::information(this,tr("提示"),tr("fuck！"),QMessageBox::Ok);
        }
        QByteArray contents=client->readAll();
        static QByteArray buf;
        if(!contents.isEmpty()){
            static QByteArray buf;
            if (!contents.isEmpty()) {
                buf.append(contents);
                if (contents.contains("\n\n\n\n")) {
                    handleUDPData(buf);
                    buf.clear();
                }
            }
        }
    });

}

Widget::~Widget() {
    delete ui;
}

void Widget::handleUDPData(const QByteArray& buf) {
    QString ack = buf.split('\r').at(0);
    QStringList ack_head = ack.split(' ');

    if (ack_head.size() < 2) {
        qDebug() << "Invalid data format";
        return;
    }

    QString responseType = ack_head.at(0);
    QString responseCode = ack_head.at(1);

    if (responseType == "USRPCONNECT") {
        handleUSRPConnect(responseCode);
    } else if (responseType == "SINGLEREQ" || responseType == "CONTINUOUSREQ" || responseType == "CONTINUOUSREQ2") {
        if (responseCode == "200") {
            int headerSize = responseType.size() + responseCode.size() + 2;
            QByteArray jsonData = buf.mid(headerSize);
            QJsonDocument doc = QJsonDocument::fromJson(jsonData);
            if (!doc.isNull()) {
                QJsonObject json = doc.object();
                updateData(json);
                updateImg(json);
            } else {
                qDebug() << "Failed to parse JSON";
            }
        } else {
            QMessageBox::information(this, tr("提示"), tr("数据包丢失，请再次点击！"), QMessageBox::Ok);
        }
    } else {
        qDebug() << "Unknown response type:" << responseType;
    }
}

void Widget::handleUSRPConnect(const QString& responseCode) {
    if (responseCode == "200") {
        QMessageBox::information(this, tr("提示"), tr("USRP连接请求成功！"), QMessageBox::Ok);
    } else if (responseCode == "401") {
        QMessageBox::warning(this, tr("警告"), tr("USRP配置出错！"), QMessageBox::Ok);
    } else {
        qDebug() << "Unknown USRP connect response code:" << responseCode;
    }
}


//// 发送USRP配置
//发送USRP配置
void Widget::on_USRP_clicked()
{
    QStringList USRP_DATA;
    USRP_DATA<<ui->frequency->currentText().toUtf8().data();
    USRP_DATA<<ui->MODE->currentText().toUtf8().data();
    USRP_DATA<<ui->TX->currentText().toUtf8().data();
    USRP_DATA<<ui->RX->currentText().toUtf8().data();
    USRP_DATA[0]=USRP_DATA[0].split(" ").at(0);
    USRP_DATA[1]=USRP_DATA[1].split(" ").at(0);
    USRP_DATA[2]=USRP_DATA[2].split(" ").at(0);
    USRP_DATA[3]=USRP_DATA[3].split(" ").at(0);

    USRP_DATA.append("frequence");USRP_DATA.append("MODE");USRP_DATA.append("TX Gain");USRP_DATA.append("RX Gain");
    QJsonObject USRP_JSON;
    for(int i=0;i<4;i++)
    {
        USRP_JSON.insert(USRP_DATA.at(i+4),USRP_DATA.at(i));
    }

    QJsonDocument doc;
    doc.setObject(USRP_JSON);
    QByteArray data=doc.toJson(QJsonDocument::Compact);
    QString strJson(data);
    client->write("USRPCONNECT\r\n\r\n");
    client->write(strJson.toUtf8().data());


}
//void Widget::on_USRP_clicked() {
//    QStringList USRP_DATA;
//    USRP_DATA << ui->frequency->currentText().toUtf8().data();
//    USRP_DATA << ui->MODE->currentText().toUtf8().data();
//    USRP_DATA << ui->TX->currentText().toUtf8().data();
//    USRP_DATA << ui->RX->currentText().toUtf8().data();
//    USRP_DATA[0] = USRP_DATA[0].split(" ").at(0);
//    USRP_DATA[1] = USRP_DATA[1].split(" ").at(0);
//    USRP_DATA[2] = USRP_DATA[2].split(" ").at(0);
//    USRP_DATA[3] = USRP_DATA[3].split(" ").at(0);

//    USRP_DATA.append("frequence");
//    USRP_DATA.append("MODE");
//    USRP_DATA.append("TX Gain");
//    USRP_DATA.append("RX Gain");
//    QJsonObject USRP_JSON;
//    for (int i = 0; i < 4; i++) {
//        USRP_JSON.insert(USRP_DATA.at(i + 4), USRP_DATA.at(i));
//    }

//    QJsonDocument doc;
//    doc.setObject(USRP_JSON);
//    QByteArray data = doc.toJson(QJsonDocument::Compact);
//    QString strJson(data);

//    QHostAddress serverAddress(ui->ip->text());
//    quint16 serverPort = ui->port->text().toInt();
//    client->writeDatagram("USRPCONNECT\r\n\r\n" + strJson.toUtf8(), serverAddress, serverPort);
//}

// 连接服务器
//void Widget::on_link_clicked() {
//    if (checked == false) {
//        if (ui->ip->text().isEmpty() || ui->port->text().isEmpty()) {
//            QMessageBox::warning(this, "警告", "请输入IP地址和端口号！",
//                                 QMessageBox::Ok);
//        } else {
//            checked = true;
//            if (!ip.contains(ui->ip->text())) {
//                ip.append(ui->ip->text().append('\n'));
//            }
//            if (!port.contains(ui->port->text())) {
//                port.append(ui->port->text().append('\n'));
//            }
//            ui->ip->setToolTip(ip);
//            ui->port->setToolTip(port);

//            ui->link->setIcon(QIcon(":/w/qt/connect.png"));
//            if (myTimer->isActive() == false) {
//                myTimer->start(10000);
//            }
//        }

//    } else {
//        checked = false;
//        ui->link->setIcon(QIcon(":/w/qt/disconnect.png"));
//        client->close();
//        ui->port->setText("8000");
//        if (myTimer->isActive() == true)
//            myTimer->stop();
//    }
//}
void Widget::on_link_clicked()
{
    if(checked==false)
    {
        if(ui->ip->text().isEmpty()||ui->port->text().isEmpty())
        {
            QMessageBox::warning(this,"警告","请输入IP地址和端口号！",QMessageBox::Ok);
        }
        else
        {
            checked=true;
            if(!ip.contains(ui->ip->text())){
                ip.append(ui->ip->text().append('\n'));
            }
            if(!port.contains(ui->port->text())){
                port.append(ui->port->text().append('\n'));
            }
            ui->ip->setToolTip(ip);
            ui->port->setToolTip(port);
            client->connectToHost(QHostAddress(ui->ip->text()),ui->port->text().toInt());
            ui->link->setIcon(QIcon(":/w/qt/connect.png"));
            if(myTimer->isActive()==false)
            {
                myTimer->start(10000);
            }
        }

    }
    else
    {
        checked=false;
        ui->link->setIcon(QIcon(":/w/qt/disconnect.png"));
        client->disconnectFromHost();
        //ui->ip->setText("10.2.2.78");
        ui->port->setText("8000");
        if(myTimer->isActive()==true)
            myTimer->stop();
    }
}

//void Widget::on_SingleReq_clicked() {
//    QStringList SINGLEREQ_DATA;
//    QHostAddress serverAddress(ui->ip->text());
//    quint16 serverPort = ui->port->text().toInt();
//    client->writeDatagram("SINGLEREQ\r\n\r\n", serverAddress, serverPort);
//}

//void Widget::on_CircleReq_clicked() {
//    if (checked_circle == false) {
//        checked_circle = true;

//        QHostAddress serverAddress(ui->ip->text());
//        quint16 serverPort = ui->port->text().toInt();
//        client->writeDatagram("CONTINUOUSREQ\r\n\r\n", serverAddress, serverPort);
//    } else {
//        checked_circle = false;
//        QHostAddress serverAddress(ui->ip->text());
//        quint16 serverPort = ui->port->text().toInt();
//        client->writeDatagram("CONTINUOUSREQ\r\n\r\n", serverAddress, serverPort);
//        QMessageBox::information(this, tr("提示"), tr("循环传输结束！"),
//                                 QMessageBox::Ok);
//    }
//}
void Widget::on_SingleReq_clicked()
{
    QStringList SINGLEREQ_DATA;
    client->write("SINGLEREQ\r\n\r\n");
}

void Widget::on_CircleReq_clicked()
{
    if(checked_circle==false)
    {
        checked_circle=true;
        client->write("CONTINUOUSREQ\r\n\r\n");
    }
    else
    {
        checked_circle=false;
        client->write("CONTINUOUSREQ\r\n\r\n");
        //        QMessageBox::(this,tr("提示"),tr("循环传输结束！"),QMessageBox::Ok);
    }
}


void Widget::on_pushButton_clicked()
{
    if(checked_circle==false)
    {
        checked_circle=true;
        client->write("CONTINUOUSREQ2\r\n\r\n");
    }
    else
    {
        checked_circle=false;
        client->write("CONTINUOUSREQ2\r\n\r\n");
        //        QMessageBox::(this,tr("提示"),tr("循环传输结束！"),QMessageBox::Ok);
    }
}
//void Widget::on_pushButton_clicked() {
//    if (checked_circle == false) {
//        checked_circle = true;

//        QHostAddress serverAddress(ui->ip->text());
//        quint16 serverPort = ui->port->text().toInt();
//        client->writeDatagram("CONTINUOUSREQ2\r\n\r\n", serverAddress, serverPort);
//    } else {
//        checked_circle = false;
//        isPaused = false;

//        QHostAddress serverAddress(ui->ip->text());
//        quint16 serverPort = ui->port->text().toInt();
//        client->writeDatagram("CONTINUOUSREQ2\r\n\r\n", serverAddress, serverPort);
//        //        QMessageBox::(this,tr("提示"),tr("循环传输结束！"),QMessageBox::Ok);
//    }
//}


void Widget::initChart(QChartView *chartView, QLineSeries *&series, QChart *&chart, const QString &title, const QString &axisXTitle, const QString &axisYTitle, const QColor &lineColor) {
    if (!chartView) {
        qWarning() << "initChart: chartView is null!";
        return;
    }
    series = new QLineSeries(this);
    chart = new QChart();
    chart->setTheme(QChart::ChartThemeBlueCerulean);

    series->setColor(lineColor);
    QPen pen = series->pen();
    pen.setWidth(2);
    series->setPen(pen);

    chart->addSeries(series);
    setupChart(chart, title, axisXTitle, axisYTitle);
    chartView->setChart(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
}

void Widget::addSecondSeries(QChart *chart, QLineSeries *&secondSeries, const QColor &lineColor) {
    secondSeries = new QLineSeries(this);
    secondSeries->setColor(lineColor);
    QPen pen = secondSeries->pen();
    pen.setWidth(2);
    secondSeries->setPen(pen);

    chart->addSeries(secondSeries);
    chart->setAxisX(chart->axisX(), secondSeries);
    chart->setAxisY(chart->axisY(), secondSeries);
}

void Widget::setupChart(QChart *chart, const QString &title, const QString &axisXTitle, const QString &axisYTitle) {
    if (!chart || chart->series().isEmpty()) {
        qWarning() << "setupChart: chart is null or series is empty!";
        return;
    }
    chart->setTitle(title);


    QFont titleFont = chart->titleFont();
    titleFont.setPointSize(12);
    titleFont.setBold(true);
    chart->setTitleFont(titleFont);
    chart->setTitleBrush(QBrush(Qt::white));

//    chart->setBackgroundBrush(QBrush(QColor(30, 30, 30)));
    chart->setBackgroundRoundness(10);
    chart->setMargins(QMargins(5, 5, 5, 5));


    QValueAxis *axisX = new QValueAxis();
    setupAxis(axisX, axisXTitle);
    axisX->setRange(1, 100);
    axisX->setTickCount(4);
    axisX->setLabelFormat("%d");
    chart->setAxisX(axisX, chart->series().first());

    QValueAxis *axisY = new QValueAxis();
    setupAxis(axisY, axisYTitle);
    chart->setAxisY(axisY, chart->series().first());
    chart->legend()->hide();
//    chart->setTheme(QChart::ChartThemeBlueCerulean);
}

void Widget::setupAxis(QValueAxis *axis, const QString &title) {
    axis->setTitleText(title);
    axis->setGridLineColor(QColor(100, 100, 100));
    axis->setTickCount(10);
    QFont axisFont = axis->labelsFont();
    axisFont.setPointSize(10);
    axis->setLabelsFont(axisFont);
    axis->setTitleBrush(QBrush(Qt::white));
    axis->setLabelsBrush(QBrush(Qt::white));
}

void Widget::updateChart(QLineSeries *series, QChart *chart, const QVector<double> &data) {
    if (!series || !chart) {
        qWarning() << "updateChart: series or chart is null!";
        return;
    }

    series->clear();
    double minY = std::numeric_limits<double>::max();
    double maxY = std::numeric_limits<double>::min();
    for (int i = 0; i < data.size(); ++i) {
        series->append(dataCount - data.size() + i + 1, data[i]);
        if (data[i] < minY) minY = data[i];
        if (data[i] > maxY) maxY = data[i];
    }

    QValueAxis *axisX = qobject_cast<QValueAxis*>(chart->axisX(series));
    if (!axisX) {
        qWarning() << "updateChart: axisX is null!";
        return;
    }

    int xMin = dataCount > 100 ? dataCount - 100 + 1 : 1;
    axisX->setRange(xMin, xMin + 99);

    axisX->setTickCount(4);

    QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axisY(series));
    if (!axisY) {
        qWarning() << "updateChart: axisY is null!";
        return;
    }

    double rangePadding = (maxY - minY) * 0.1;  // 增加10%的padding
    axisY->setRange(minY - rangePadding, maxY + rangePadding);
}

void Widget::updateChart2(QLineSeries *series1, QLineSeries *series2, QChart *chart, const QVector<double> &data1, const QVector<double> &data2) {
    if (!series1 || !series2 || !chart) {
        qWarning() << "updateChart: series or chart is null!";
        return;
    }

    series1->clear();
    series2->clear();

    double minY = std::numeric_limits<double>::max();
    double maxY = std::numeric_limits<double>::min();

    for (int i = 0; i < data1.size(); ++i) {
        series1->append(dataCount - data1.size() + i + 1, data1[i]);
        if (data1[i] < minY) minY = data1[i];
        if (data1[i] > maxY) maxY = data1[i];
    }

    for (int i = 0; i < data2.size(); ++i) {
        series2->append(dataCount - data2.size() + i + 1, data2[i]);
        if (data2[i] < minY) minY = data2[i];
        if (data2[i] > maxY) maxY = data2[i];
    }

    QValueAxis *axisX = qobject_cast<QValueAxis*>(chart->axisX(series1));
    if (!axisX) {
        qWarning() << "updateChart: axisX is null!";
        return;
    }

    int xMin = dataCount > 100 ? dataCount - 100 + 1 : 1;
    axisX->setRange(xMin, xMin + 99);
    axisX->setTickCount(4);

    QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axisY(series1));
    if (!axisY) {
        qWarning() << "updateChart: axisY is null!";
        return;
    }

    double rangePadding = (maxY - minY) * 0.1;  // 增加10%的padding
    axisY->setRange(minY - rangePadding, maxY + rangePadding);
}


void Widget::updateTableData(double ber, double bler, double snr) {
    if (isPaused) {
        return;
    }
    dataCount++;
//    qDebug() << dataCount;
    if (vber.count() < 101) {
        vber.append(ber);
    } else {
        vber.pop_front();
        vber.append(ber);
    }
    updateChart(berSeries, berChart, vber);

    if (vbler.count() < 101) {
        vbler.append(bler);
    } else {
        vbler.pop_front();
        vbler.append(bler);
    }
    updateChart(blerSeries, blerChart, vbler);

    if (vsnr.count() < 101) {
        vsnr.append(snr);
        vtsnr.append(temp_snr);
    } else {
        vsnr.pop_front();
        vsnr.append(snr);
        vtsnr.pop_front();
        vtsnr.append(temp_snr);
    }
    updateChart2(snrSeries, tsnrSeries, snrChart, vsnr, vtsnr);
}

void Widget::on_cleanTableButton_clicked() {
    if (xinzuoSeries) xinzuoSeries->clear();
    if (berSeries) berSeries->clear();
    if (blerSeries) blerSeries->clear();
    if (snrSeries) snrSeries->clear();
    if (tsnrSeries) tsnrSeries->clear();

    QValueAxis *axisX = qobject_cast<QValueAxis*>(snrChart->axes(Qt::Horizontal).first());
    QValueAxis *axisY = qobject_cast<QValueAxis*>(snrChart->axes(Qt::Vertical).first());
    if (axisX && axisY) {
        axisX->setRange(1, 100);
        axisY->setRange(1, 100);
    }

    dataCount = 0;
    ui->noise->clear();
    ui->signal->clear();
    ui->snr->clear();
    ui->bler->clear();
    ui->ber->clear();
    if (ui->pic) ui->pic->clear();
    if (ui->pic_7) ui->pic_7->clear();
}



void Widget::on_pauseButton_clicked() {
    if (!checked_circle) {
        isPaused = false;
        ui->pauseButton->setText("暂停");
        return;
    }
    isPaused = !isPaused;
    if (isPaused) {
        ui->pauseButton->setText("恢复");
    } else {
        ui->pauseButton->setText("暂停");
    }
}

void Widget::updateData(const QJsonObject &circlereq_json) {
    double snr =
        circlereq_json.value("SNR").toDouble();
    double bler =
        100 *
        circlereq_json.value("BLER").toDouble();
    double ber =
        100 *
        circlereq_json.value("BER").toDouble();

    if (mean_snr.count() < 100) {
        mean_snr.append(snr);
        sum_meansnr += snr;
        temp_snr = sum_meansnr / mean_snr.count();
    } else {
        mean_snr.append(snr);
        mean_snr.pop_front();
        sum_meansnr = 0;
        for (int i = 0; i < 100; i++) {
            sum_meansnr += mean_snr[i];
        }
        temp_snr = sum_meansnr / mean_snr.count();
    }
    QString SNR = QString::number(snr, 'f', 2);
    QString BLER = QString::number(bler, 'f', 2);
    QString BER = QString::number(ber, 'f', 2);
    QString TSNR =
        QString::number(temp_snr, 'f', 2);

    ui->noise->clear();
    ui->noise->setText("1Mbps");
    ui->signal->clear();
    ui->signal->setText("4mW");
    ui->snr->clear();
    ui->snr->setText(TSNR + "dB");
    ui->bler->clear();
    ui->bler->setText(BLER + "%");
    ui->ber->clear();
    ui->ber->setText(BER + "%");

    if (!xinzuoSeries) {
        xinzuoSeries = new QScatterSeries();
        xinzuoSeries->setMarkerSize(5);
        xinzuoSeries->setBorderColor(QColor(0, 0, 255));
        xinzuoSeries->setBrush(QBrush(QColor(0, 0, 255)));

        xinzuoChart = new QChart();
        xinzuoChart->addSeries(xinzuoSeries);
        xinzuoChart->legend()->hide();

        QValueAxis *axisX = new QValueAxis();
        axisX->setRange(-4, 4);
        axisX->setTitleText("Constellation Diagram");
        setupAxisStyling(axisX);

        QValueAxis *axisY = new QValueAxis();
        axisY->setRange(-4, 4);
        setupAxisStyling(axisY);

        xinzuoChart->setAxisX(axisX, xinzuoSeries);
        xinzuoChart->setAxisY(axisY, xinzuoSeries);
        ui->Constellation123->setChart(xinzuoChart);
    }

    QJsonArray real_part = circlereq_json.value("real_part").toArray();
    QJsonArray real_imag = circlereq_json.value("imag_part").toArray();

    xinzuoSeries->clear();
    for (int i = 0; i < real_part.size(); ++i) {
        xinzuoSeries->append(real_part[i].toDouble(), real_imag[i].toDouble());
    }

    updateTableData(ber, bler, snr);
}

void Widget::setupAxisStyling(QValueAxis *axis) {
    axis->setLabelsVisible(true);
    axis->setLabelsAngle(0);
    axis->setLabelsColor(Qt::black);
    axis->setGridLineVisible(true);
    QFont font = axis->labelsFont();
    font.setBold(true);
    font.setPointSize(9);
    axis->setLabelsFont(font);
}

void Widget::updateImg(const QJsonObject &circlereq_json) {
    int send_f = circlereq_json.value("STA").toInt();
    QLabel *targetLabel = nullptr;
    QString noiseText = "1Mbps";
    QString defaultImagePath = ":/w/qt/1.png";

    switch (send_f) {
    case 0:
        targetLabel = ui->pic;
        break;
    case 3:
        targetLabel = ui->pic_7;
        break;
    default:
        qDebug() << "Invalid send_f value:" << send_f;
        return;
    }

    QByteArray img = circlereq_json.value("PICTURE").toVariant().toByteArray();
    ui->noise->setText(noiseText);
    ui->pic->clear();
    ui->pic_7->clear();

    if (img.toStdString() == "{}") {
        QPixmap defaultImage(defaultImagePath);
        targetLabel->setPixmap(defaultImage);
    } else {
        QByteArray imgData = QByteArray::fromBase64(img);
        QImage pic;
        pic.loadFromData(imgData);
        pic = pic.scaled(targetLabel->size());
        targetLabel->setPixmap(QPixmap::fromImage(pic));
    }
}
